"""
JWT的token值签发和验证流程
"""
import json
import base64
import hmac,hashlib

# 1、头信息
# "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
header = {
  'typ': 'JWT',
  'alg': 'HS256' # 生成签名所用的算法是sha256哈希算法/签名算法/散列运算/加密算法
}
header = json.dumps(header) # string: "{"alg": "HS256", "typ": "JWT"}"
header = base64.b64encode(header.encode()) # b'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9'
print("头信息：", header.decode())

# 2、载荷信息(用户信息)
payload = {
    "user_id": 1,
    "age": 18,
    "user_name": "weiwei",

    "iss": "chuanzhi",
    "sub": "zhangsan",
}
payload = json.dumps(payload)
payload = base64.b64encode(payload.encode())
print("载荷信息：", payload.decode())


# 3、签名signature
# 经过哈希散列运算："TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
# 3.1 获取签名加密的原始数据(哪一部分数据不被篡改？！)
# b"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9"
msg = header + b'.' + payload
# 3.2 使用sha256哈希算法计算出一个签名
# 3.2.1 构建哈希对象
SECRET_KEY = b'j*h(69kj^)ofyw+re!3!fpsh28a^wnm9iv1xv@9mi%^$)(dgm='
hash_obj = hmac.new(SECRET_KEY, msg=msg, digestmod=hashlib.sha256)
# 3.2.2 通过哈希对象，获得签名
signature = hash_obj.hexdigest()
# 根据header和payload进行sha256得出签名。这种操作是不可逆
print("签名：", signature)

# 最终签发生成的token值
JWT_TOKEN = header.decode() + '.' + payload.decode() + '.' + signature
print("token值：", JWT_TOKEN)


print("-------华丽的分割线-----------")
print("以下，模拟jwt验证流程:")


# 1、模拟前端传来token值
jwt_token_from_font = JWT_TOKEN # 没有篡改
# jwt验证原理：
# 加密的msg 配合 SECRET_KEY 进行哈希运算得出一个不可逆的签名signature！！
# 思考：如果我更改了header或者payload，在没有SECRET_KEY情况下，能否得到对应的签名？！
# 结论：在没有SECRET_KEY的时候，是无法生成与之对应的第三部分签名数据！
# 如何验证？
# 答：提取header和payload，配合后端密钥再一次获得新签名，把新的签名和原签名比对，如果一致说明未篡改，否则篡改了！
# 2.1 提取前端传来的token的三部分数据
header_from_font = jwt_token_from_font.split('.')[0]
payload_from_font = jwt_token_from_font.split('.')[1]
signature_from_font = jwt_token_from_font.split('.')[2]
# 2.2 针对前端传来的header和payload，配合后端密钥，再一次加密得出与之匹配的signature
msg = header_from_font + '.' + payload_from_font
new_signature = hmac.new(SECRET_KEY, msg=msg.encode(), digestmod=hashlib.sha256).hexdigest()
# 2.3 把新生成的签名和前端传来的签名比对
if new_signature == signature_from_font:
    print("数据是完整的！")
else:
    print("数据被篡改了！")

